package com.maslyk.invitation.jsfcontroller;


import java.text.MessageFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.myfaces.component.html.ext.HtmlDataTable;
import org.apache.myfaces.custom.fileupload.UploadedFile;
import org.apache.myfaces.trinidad.component.UIXIterator;
import org.apache.myfaces.trinidad.component.core.data.CoreTable;
import org.apache.myfaces.trinidad.component.core.input.CoreSelectOneChoice;
import org.apache.myfaces.trinidad.context.RequestContext;
import org.apache.myfaces.trinidad.event.ReturnEvent;

import com.maslyk.configuration.ConfigurationManager;
import com.maslyk.invitation.BeanService;
import com.maslyk.invitation.entitybean.Attachment;
import com.maslyk.invitation.entitybean.Comment;
import com.maslyk.invitation.entitybean.Insertion;
import com.maslyk.invitation.entitybean.Invitation;
import com.maslyk.invitation.entitybean.Order;
import com.maslyk.invitation.entitybean.Product;
import com.maslyk.invitation.entitybean.Text;
import com.maslyk.invitation.entitybean.Vigniette;
import com.maslyk.invitation.enums.AdditionalStatusEnum;
import com.maslyk.invitation.enums.LocalNames;
import com.maslyk.invitation.enums.OrderStatusEnum;
import com.maslyk.invitation.enums.RecordTypeEnum;
import com.maslyk.invitation.enums.ViewIdentityEnum;
import com.maslyk.invitation.exception.LogicalException;
import com.maslyk.invitation.page.Utils;
import com.maslyk.invitation.printout.XSLTools;
import com.maslyk.invitation.service.PersistenceService;
import com.maslyk.invitation.service.email.MessagingEmailService;
import com.maslyk.invitation.to.CurrentUserTO;
import com.maslyk.invitation.to.OrderSearchCondition;
import com.maslyk.invitation.to.PassingParameter;
import com.maslyk.invitation.to.SessionDataTO;
import com.maslyk.invitation.utils.StringUtils;

public class OrderController
{
    private CoreTable textListDataTable;
    private CoreTable selectedTextListDataTable;
    private HtmlDataTable invitationListDataTable;
    private HtmlDataTable insertionListDataTable;
    private HtmlDataTable vignietteListDataTable;
    private HtmlDataTable productListDataTable;
    private CoreTable orderListDataTable;
    private UIXIterator attachmentIterator;
    private UIXIterator commentIterator;
    private CoreSelectOneChoice orderNumberBinding;

    Logger log = Logger.getLogger(OrderController.class);
    
    public UIXIterator getAttachmentIterator()
    {
        return attachmentIterator;
    }

    public void setAttachmentIterator(UIXIterator attachmentIterator)
    {
        this.attachmentIterator = attachmentIterator;
    }
    
    public OrderController()
    {
    	resetSearchFilter(null);
    }

    public String addInvitationToOrder()
    {
        Invitation invitation = getInvitationBean();
        Order orderEntity = getOrderBean();
        invitation.setOrderID(orderEntity);
        orderEntity.getInvitationEntityCollection().add(invitation);
        BeanService.putSessionScopeBean("invitationBean", null);
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_FORM);
        return null;
    }

    public String addInsertionToOrder()
    {
        Insertion insertion = getInsertionBean();
        Order orderEntity = getOrderBean();
        insertion.setOrder(orderEntity);
        orderEntity.getInsertionCollection().add(insertion);
        BeanService.putSessionScopeBean("insertionBean", null);
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_FORM);
        return null;
    }

    public String saveInsertionItem()
    {
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_FORM);
        return null;
    }

    public String addVignietteToOrder()
    {
        Vigniette vigniette = getVignietteBean();
        Order orderEntity = getOrderBean();
        vigniette.setOrder(orderEntity);
        orderEntity.getVignietteCollection().add(vigniette);
        BeanService.putSessionScopeBean("vignietteBean", null);
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_FORM);
        return null;
    }

    public String addProductToOrder()
    {
        Product product = getProductBean();
        Order orderEntity = getOrderBean();
        product.setOrder(orderEntity);
        orderEntity.getProductCollection().add(product);
        BeanService.putSessionScopeBean("productBean", null);
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_FORM);
        return null;
    }

    public String saveVignietteItem()
    {
        Vigniette vigniette = getVignietteBean();
        Order orderEntity = getOrderBean();
        vigniette.setOrder(orderEntity);
        orderEntity.getVignietteCollection().add(vigniette);
        BeanService.putSessionScopeBean("vignietteBean", null);
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_FORM);
        return null;
    }

    public String saveProductItem()
    {
        BeanService.putSessionScopeBean("productBean", null);
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_FORM);
        return null;
    }

    public CoreTable getTextListDataTable()
    {
        return textListDataTable;
    }

    public void setTextListDataTable(CoreTable textListDataTable)
    {
        this.textListDataTable = textListDataTable;
    }

    public boolean isSelectedTextRow()
    {
        return getInvitationBean().getTextList().contains((Text) textListDataTable.getRowData());
    }

    public String editInvitationInOrder()
    {
        Invitation editedInvitation = (Invitation) invitationListDataTable.getRowData();
        BeanService.putSessionScopeBean("invitationBean", editedInvitation);
        SessionDataTO.setCurrentView(ViewIdentityEnum.INVITATION_FORM);
        return null;
    }

    public String newInvitationItem()
    {
        BeanService.putSessionScopeBean("invitationBean", new Invitation());
        SessionDataTO.setCurrentView(ViewIdentityEnum.INVITATION_FORM);
        return null;
    }
    
    public String newVignetteItem()
    {
        BeanService.putSessionScopeBean("vignetteBean", new Vigniette());
        SessionDataTO.setCurrentView(ViewIdentityEnum.VIGNETTE_FORM);
        return null;
    }

    public String newInsertionItem()
    {
        BeanService.putSessionScopeBean("insertionBean", new Insertion());
        SessionDataTO.setCurrentView(ViewIdentityEnum.INSERTION_FORM);
        return null;
    }

    public String newProductItem()
    {
        BeanService.putSessionScopeBean("productBean", new Product());
        SessionDataTO.setCurrentView(ViewIdentityEnum.PRODUCT_FORM);
        return null;
    }

    public String removeInvitationFromOrder() throws Exception
    {
        Order order = getOrderBean();
        Invitation invitation = (Invitation) invitationListDataTable.getRowData();

        if(invitation.getId() != null)
        	PersistenceService.getInstance().removeInvitation(invitation);
        
        order.getInvitationEntityCollection().remove(invitation);
        return null;
    }

    public String removeInsertionFromOrder() throws Exception
    {
        Order order = getOrderBean();
        Insertion insertion = (Insertion) insertionListDataTable.getRowData();

        if(insertion.getId() != null)
        	PersistenceService.getInstance().removeInsertion(insertion);
        
        order.getInsertionCollection().remove(insertion);
        return null;
    }

    public String removeProductFromOrder() throws Exception
    {
        Order order = getOrderBean();
        Product product = (Product) productListDataTable.getRowData();

        if(product.getId() != null)
        	PersistenceService.getInstance().removeProduct(product);

        order.getProductCollection().remove(product);
        return null;
    }

    public String editInsertionInOrder()
    {
        BeanService.putSessionScopeBean("insertionBean", insertionListDataTable.getRowData());
        SessionDataTO.setCurrentView(ViewIdentityEnum.INSERTION_FORM);

        return null;
    }

    public String editProductInOrder()
    {
        BeanService.putSessionScopeBean("productBean", productListDataTable.getRowData());
        SessionDataTO.setCurrentView(ViewIdentityEnum.PRODUCT_FORM);

        return null;
    }

    public String removeVignietteFromOrder() throws Exception
    {
        Order order = getOrderBean();
        Vigniette vigniette = (Vigniette) vignietteListDataTable.getRowData();

        if(vigniette.getId() != null)
        	PersistenceService.getInstance().removeVigniette(vigniette);
        
        order.getVignietteCollection().remove(vigniette);
        
        return null;
    }

    public String editVignietteInOrder()
    {
        BeanService.putSessionScopeBean("vignietteBean", vignietteListDataTable.getRowData());
        SessionDataTO.setCurrentView(ViewIdentityEnum.VIGNETTE_FORM);
        return null;
    }

    public HtmlDataTable getInvitationListDataTable()
    {
        return invitationListDataTable;
    }

    public void setInvitationListDataTable(HtmlDataTable invitationListDataTable)
    {
        this.invitationListDataTable = invitationListDataTable;
    }

    // funkcja sprawdza czy pozycja zamowienia jest nowa czy edytowana.
    public boolean isEditedInvitation()
    {
        return getOrderBean().getInvitationEntityCollection().contains(BeanService.getSessionScopeBean("invitationBean"));
    }

    public Order getOrderBean()
    {
        return (Order) BeanService.getSessionScopeBean("orderBean");
    }

    public String editInvitationItem()
    {
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_FORM);
        return null;
    }

    public String insertOrder() throws LogicalException, Exception
    {
        Order order = getOrderBean();
        CurrentUserTO currentUser = (CurrentUserTO) BeanService.getSessionScopeBean("currentUserTO");

        order.setSalesmanID(currentUser.getCurrentSalesman());
        order.setResponsible(currentUser.getCurrentSalesman());
        PersistenceService.getInstance().saveOrder(order);
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_PREVIEW);
        return null;
    }

    public CoreTable getOrderListDataTable()
    {
        return orderListDataTable;
    }

    public void setOrderListDataTable(CoreTable orderListDataTable)
    {
        this.orderListDataTable = orderListDataTable;
    }

    @SuppressWarnings("unchecked")
	public List<Order> getOrderList()
    {
        return (List<Order>) BeanService.getSessionScopeBean("orderFoundList");
    }

    public void setOrderList(List<Order> orderList)
    {
        BeanService.putSessionScopeBean("orderFoundList", orderList);
    }

    public String editOrder() throws Exception
    {
        Order ordr = PersistenceService.getInstance().findOrderEntity(((Order)orderListDataTable.getRowData()).getId());
        BeanService.putSessionScopeBean("orderBean", ordr);
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_FORM);
        
        return null;
    }

    public String removeOrder() throws Exception
    {
    	PersistenceService.getInstance().removeOrder((Order) orderListDataTable.getRowData());
        OrderSearchCondition orderSearchCondition = (OrderSearchCondition) BeanService.getSessionScopeBean("OrderSearchCondition");
        setOrderList(PersistenceService.getInstance().searchOrders(orderSearchCondition));
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_LIST);
        return null;
    }

    public String orderPreviewButton()
    {
        BeanService.putSessionScopeBean("orderBean", orderListDataTable.getRowData());
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_FORM);
        SessionDataTO.setReadOnlyView();
        return null;
    }

    public String updateOrder() throws LogicalException, Exception
    {
        Order order = getOrderBean();
        CurrentUserTO currentUser = (CurrentUserTO) BeanService.getSessionScopeBean("currentUserTO");
        order.setSalesmanID(currentUser.getCurrentSalesman());
        PersistenceService.getInstance().saveOrder(order);
        BeanService.putSessionScopeBean("orderBean", null);
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_LIST);
        return null;
    }

    public String cancelOrder() throws Exception
    {
//    	PersistenceService.getInstance().attachmentBO();
    	
        Order order = getOrderBean();
        order.setStatus(OrderStatusEnum.ANULOWANE.ordinal());
        PersistenceService.getInstance().saveOrder(order);
        BeanService.putSessionScopeBean("orderBean", null);
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_LIST);
        return null;
    }

    public String printOrder() throws Exception
    {
        Order order = getOrderBean();
        XSLTools.openPDF(FacesContext.getCurrentInstance(), "zamowienie-"+order.getNumber().replace("/", "-"), order);
        return null;
    }

    public String searchOrders()
    {
        OrderSearchCondition OrderSearchCondition = (OrderSearchCondition) BeanService.getSessionScopeBean("OrderSearchCondition");
        setOrderList(PersistenceService.getInstance().searchOrders(OrderSearchCondition));
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_LIST);
        return null;
    }
    
    public void resetSearchFilter(ActionEvent event)
    {
    	OrderSearchCondition condition = new OrderSearchCondition();
    	CurrentUserTO currentUser = (CurrentUserTO) BeanService.getSessionScopeBean("currentUserTO");
    	condition.setSalesmanResponsible(currentUser.getCurrentSalesman());
    	
    	BeanService.putSessionScopeBean("OrderSearchCondition", condition);
    }

    public static Invitation getInvitationBean()
    {
        return (Invitation) BeanService.getSessionScopeBean("invitationBean");
    }

    public static Insertion getInsertionBean()
    {
        return (Insertion) BeanService.getSessionScopeBean("insertionBean");
    }

    public static Vigniette getVignietteBean()
    {
        return (Vigniette) BeanService.getSessionScopeBean("vignietteBean");
    }

    public static Product getProductBean()
    {
        return (Product) BeanService.getSessionScopeBean("productBean");
    }

    public String orderPreview()
    {
        Order order = getOrderBean();
        if(order.getStatus().equals(3) && order.getReceipt() == null)
        {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Brak paragonu", "Dla statusu ODEBRANE paragon musi zostac podany."));
            return null;
        }

        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_PREVIEW);
        return null;
    }

    public HtmlDataTable getInsertionListDataTable()
    {
        return insertionListDataTable;
    }

    public void setInsertionListDataTable(HtmlDataTable insertionListDataTable)
    {
        this.insertionListDataTable = insertionListDataTable;
    }

    public HtmlDataTable getVignietteListDataTable()
    {
        return vignietteListDataTable;
    }

    public void setVignietteListDataTable(HtmlDataTable vignietteListDataTable)
    {
        this.vignietteListDataTable = vignietteListDataTable;
    }
    
    public void removeSelectedTexts(ActionEvent event)
    {
        Invitation invitation = getInvitationBean();
        
        for (Object key : selectedTextListDataTable.getSelectedRowKeys())
        {
            selectedTextListDataTable.setRowKey(key);
            invitation.getTextList().remove((Text) selectedTextListDataTable.getRowData());
        }
    }

    public CoreTable getSelectedTextListDataTable()
    {
        return selectedTextListDataTable;
    }

    public void setSelectedTextListDataTable(CoreTable selectedTextListDataTable)
    {
        this.selectedTextListDataTable = selectedTextListDataTable;
    }

    public void addEmptyComment(ActionEvent event)
    {
        Comment comment = new Comment();
        BeanService.putSessionScopeBean("commentBean", comment);
    }
    
    public void cancelAddComment(ActionEvent event)
    {
        BeanService.putSessionScopeBean("commentBean", null);
    }

    public String saveComment() throws Exception
    {
        Comment comment = (Comment) BeanService.getSessionScopeBean("commentBean");
        fillComment(comment);
        comment = PersistenceService.getInstance().createComment(comment);
        Order ordr = getOrderBean();
        ordr.getCommentList().add(comment);
        BeanService.putSessionScopeBean("commentBean", null);
        return null;
    }

    public HtmlDataTable getProductListDataTable()
    {
        return productListDataTable;
    }

    public void setProductListDataTable(HtmlDataTable productListDataTable)
    {
        this.productListDataTable = productListDataTable;
    }

    public void uploadFileListener(ValueChangeEvent upload) throws Exception
    {
        UploadedFile file = (UploadedFile) upload.getNewValue();

        if(file == null)
            return;
        
        String filename = file.getName().replace(' ', '_');
        filename = StringUtils.replacePolishSpecialCharacters(filename);
        
        Order ordr = getOrderBean();
        Attachment att = new Attachment(null, filename, file.getBytes(), ordr);
        
        if(ordr.getAttachmentList().contains(att))
        	throw new LogicalException(LocalNames.LOGICAL_ERROR_HEADER, "Istnieje juz zalacznik o takiej nazwie. Zmien nazwe i sprobuj raz jeszcze.");
        
        att = PersistenceService.getInstance().createAttachment(att);
        ordr.getAttachmentList().add(att);
    }

    public void selectAttachment(ActionEvent action) throws Exception
    {
        Attachment attachment = (Attachment) attachmentIterator.getRowData();
        
        if(attachment.getData()== null)
        	throw new LogicalException(LocalNames.LOGICAL_ERROR_HEADER,"Plik jest pusty!");
        
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
        //response.setContentType("application/pdf");
        response.setHeader("Content-disposition", "attachment; filename=" + attachment.getName());
        response.setContentLength(attachment.getData().length);
        response.getOutputStream().write(attachment.getData());
        response.flushBuffer();
        context.responseComplete();
    }

    public void removeAttachment(ActionEvent action) throws Exception
    {
        Attachment attachment = (Attachment) attachmentIterator.getRowData();
        Order ordr = getOrderBean();
        ordr.getAttachmentList().remove(attachment);
        PersistenceService.getInstance().removeAttachment(attachment);
    }

    public void statusChanged(ValueChangeEvent event) throws LogicalException
    {
        Order ordr = getOrderBean();

        StringBuilder text = new StringBuilder();
        Comment comment = new Comment();
        fillComment(comment);
        text.append("Zmiana statusu z "+ OrderStatusEnum.getStatus((Integer)event.getOldValue())+" na " + OrderStatusEnum.getStatus((Integer)event.getNewValue()));
        comment.setNote(text.toString());
        ordr.getCommentList().add(comment);
    }
    
    public void recordTypeChanged(ValueChangeEvent event) throws LogicalException
    {
    	RecordTypeEnum newType = (RecordTypeEnum) event.getNewValue();
    	
    	if(newType.equals(RecordTypeEnum.OFFER))
    		orderNumberBinding.setRendered(false);
    	else
    		orderNumberBinding.setRendered(true);
    }

    private void fillComment(Comment comment)
    {
        comment.setOrderID(getOrderBean());
        CurrentUserTO user = (CurrentUserTO) BeanService.getSessionScopeBean("currentUserTO");
        comment.setSalesmanID(user.getCurrentSalesman());
        comment.setRegistrationDate(new Date());
    }

    public void responsibleChanged(ValueChangeEvent event)
    {
        Order ordr = getOrderBean();

        StringBuilder text = new StringBuilder();
        Comment comment = new Comment();
        fillComment(comment);
        text.append("Przydzielono zam\u00f3wienie do: "+event.getNewValue().toString());
        comment.setNote(text.toString());
        ordr.getCommentList().add(comment);
    }

    public void sendEmailToClient(ActionEvent event) throws LogicalException, Exception
    {
        Order ordr = getOrderBean();

        if(ordr.getEmail() == null || ordr.getEmail().trim().length() == 0 || ordr.getShippingNo() == null || ordr.getShippingNo().trim().length() == 0)
            return;
        
        MessageFormat subject = new MessageFormat(ConfigurationManager.getInstance().getSHIPPING_EMAIL_SUBJECT(), new Locale("pl"));
        String content = Utils.getFileContent(ConfigurationManager.getInstance().getSHIPPING_EMAIL_CONTENT_FILE());

        MessageFormat contentMsgFormat = new MessageFormat(content, new Locale("pl"));
        String subjectTxt = subject.format(new String[]{ordr.getNumber()});
        String contentTxt = contentMsgFormat.format(new String[]{ordr.getShippingNo()});
        
        MessagingEmailService emailService = new MessagingEmailService();
        emailService.sendMessage(ordr.getEmail().trim(), contentTxt, subjectTxt);

        Comment comment = new Comment();
        fillComment(comment);
        comment.setNote("Wys\u0142ano emaila o tresci: \n\n"+ contentTxt);
        ordr.getCommentList().add(comment);

        PersistenceService.getInstance().saveOrder(ordr);
    }

    public void passingReturned(ReturnEvent event) throws LogicalException, Exception
    {
        PassingParameter params = (PassingParameter) event.getReturnValue();
        if(params == null)
            return;

        Order ordr = getOrderBean();
        ordr.setResponsible(params.getSalesman());
        StringBuilder text = new StringBuilder();
        Comment comment = new Comment();
        fillComment(comment);
        text.append("Przydzia\u0142 zam\u00f3wienia: "+ordr.getNumber()+" do: "+ordr.getResponsible().toString()+"\n\n");
        text.append(params.getComment());
        comment.setNote(text.toString());
        ordr.getCommentList().add(comment);
        PersistenceService.getInstance().saveOrder(ordr);
        MessagingEmailService emailService = new MessagingEmailService();
        emailService.sendMessage(params.getSalesman().getPersonid().getEmail(), text.toString(), "Przydzia\u0142 zam\u00f3wienia: " +ordr.getNumber());
        SessionDataTO.setCurrentView(ViewIdentityEnum.ORDER_LIST);
    }
    
    @SuppressWarnings("unchecked")
	public void returnTextList(ReturnEvent event)
    {
		List<Text> textList = (List<Text>) event.getReturnValue();
        getInvitationBean().getTextList().addAll(textList);
    }

    public String preparePassingData()
    {
        PassingParameter params = (PassingParameter) BeanService.getRequestScopeBean("PassingParameter");
        RequestContext.getCurrentInstance().returnFromDialog(params, null);
        return null;
    }

    public void commentRemove(ActionEvent event) throws Exception
    {
    	Comment comment = (Comment) commentIterator.getRowData();
    	Order ordr = getOrderBean();
    	ordr.getCommentList().remove(comment);
    	
    	if(comment.getId() == null)
    		return;

    	PersistenceService.getInstance().removeComment(comment);
    }
    
	public UIXIterator getCommentIterator() 
	{
		return commentIterator;
	}

	public void setCommentIterator(UIXIterator commentIterator) 
	{
		this.commentIterator = commentIterator;
	}
	
	public void makeOrderFromOffer(ActionEvent event) throws Exception
	{
		Order ordr = getOrderBean();
		try 
		{
			PersistenceService.getInstance().changeOfferToOrder(ordr);
		} catch (Exception e) 
		{
			log.error("Blad zmiany oferty na zamowienie: ", e);
			throw e;
		}
	}
	
	public void additionalStatusChanged(ValueChangeEvent event)
	{
		Integer additionalStatus = (Integer) event.getNewValue();
		AdditionalStatusEnum newStatus = AdditionalStatusEnum.getStatus(additionalStatus);
		Order ordr = getOrderBean();
		
		if((newStatus.equals(AdditionalStatusEnum.ZALICZKA) || newStatus.equals(AdditionalStatusEnum.CALOSC)) &&
				(ordr.getPaymentConfirmation() == null || ordr.getPaymentConfirmation().length() == 0))
			FacesContext.getCurrentInstance().addMessage("additionalStatus", new FacesMessage(FacesMessage.SEVERITY_WARN,"Uwaga","Wymagane jest wypełnienie potwierdzenia wpłaty"));	
	}

	public CoreSelectOneChoice getOrderNumberBinding() {
		return orderNumberBinding;
	}

	public void setOrderNumberBinding(CoreSelectOneChoice orderNumberBinding) {
		this.orderNumberBinding = orderNumberBinding;
	}
}
